package com.imooc.threadpoolexecutor;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

/**
 * @author ChangLiang
 * @date 2019/3/6
 */
public class ThreadPoolExecutorTest {
    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolExecutorTest.class);

    @Test
    public void test() {
        LOGGER.info("begin test");
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("test-pool-%d").build();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                1
                , 1
                , 0L
                , TimeUnit.MILLISECONDS
                , new ArrayBlockingQueue<>(1)
                , threadFactory
                , ((r, executor) -> LOGGER.info("被拒绝任务为" + r.toString()))
        );
        for (int i = 0; i < 5; i++) {
            final int j = 1;
            threadPoolExecutor.submit(()->LOGGER.info(j+"处理业务"));

//            threadPoolExecutor.execute(()->LOGGER.info(j+"处理业务"));
//            new Thread(() -> LOGGER.info(j+"处理业务")).start();
        }
        threadPoolExecutor.shutdown();
        try {
            // 该方法调用会被阻塞，直到所有任务执行完毕并且shutdown请求被调用，
            // 或者参数中定义的timeout时间到达或者当前线程被打断，
            // 这几种情况任意一个发生了就会导致该方法的执行
            threadPoolExecutor.awaitTermination(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test02() {
        LOGGER.info("begin test02");
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("test02-pool-%d").build();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                1
                , 1  // 设置为1 或 2 其是会进行扩容的
                , 0L
                , TimeUnit.MILLISECONDS
                , new ArrayBlockingQueue<>(1)  // 这个设置为1或3 效果是不同的
                , threadFactory
                , ((r, executor) -> LOGGER.info("被拒绝任务为" + r.toString()))
        ){
            @Override
            protected void beforeExecute(Thread t, Runnable r) {
                super.beforeExecute(t, r);
                LOGGER.info(r.getClass().getName()+"线程执行之前");
            }

            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
                LOGGER.info("线程执行之后");
            }
        };
        for (int i = 0; i < 5; i++) {
            final int j = 1;
//            threadPoolExecutor.submit(()->LOGGER.info(j+"处理业务"));

            threadPoolExecutor.execute(()->LOGGER.info(j+"处理业务"));
//            new Thread(() -> LOGGER.info(j+"处理业务")).start();
        }
        threadPoolExecutor.shutdown();
        try {
            // 该方法调用会被阻塞，直到所有任务执行完毕并且shutdown请求被调用，
            // 或者参数中定义的timeout时间到达或者当前线程被打断，
            // 这几种情况任意一个发生了就会导致该方法的执行
            threadPoolExecutor.awaitTermination(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test03() {
        LOGGER.info("begin test03");

        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("test03-pool-%d").build();

        //如果corePoolSize与maximumPoolSize不同，好像经常不能完全执行
        //而且设置为不同，我也没看到有扩容的行为
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                1
                , 5
                , 1000L
                , TimeUnit.MILLISECONDS
                , new ArrayBlockingQueue<>(3)
                , threadFactory
                , ((r, executor) -> LOGGER.info("被拒绝任务为" + r.toString()))
        ){
            @Override
            protected void beforeExecute(Thread t, Runnable r) {
                super.beforeExecute(t, r);
                LOGGER.info(r.getClass().getName()+"线程执行之前");
            }

            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
                Class<? extends Runnable> rClass = r.getClass();
                try {
                    LiftOff runnable = (LiftOff) rClass.newInstance();
                    LOGGER.info(runnable.getTag()+"这类线程执行之后");
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        };
        for (int i = 0; i < 10; i++) {
            final int j = 1;
            threadPoolExecutor.execute(new LiftOff());
        }
        threadPoolExecutor.shutdown();
        try {
            // 该方法调用会被阻塞，直到所有任务执行完毕并且shutdown请求被调用，
            // 或者参数中定义的timeout时间到达或者当前线程被打断，
            // 这几种情况任意一个发生了就会导致该方法的执行
            threadPoolExecutor.awaitTermination(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test04() {
        LOGGER.info("begin submit test04");
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("test04-pool-%d").build();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                5
                , 5
                , 0L
                , TimeUnit.MILLISECONDS
                , new ArrayBlockingQueue<>(3)
                , threadFactory
                , ((r, executor) -> LOGGER.info("被拒绝任务为" + r.toString()))
        ){
            @Override
            protected void beforeExecute(Thread t, Runnable r) {
                super.beforeExecute(t, r);
                LOGGER.info(r.getClass().getName()+"线程执行之前");
            }

            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
                Class<? extends Runnable> rClass = r.getClass();
                /*try {
                    ///Caused by: java.lang.NoSuchMethodException: java.util.concurrent.FutureTask.<init>()
                    ///可能没办法通过反射方式来创建FutureTask
                    *//*FutureTask<Thread02> runnable = (FutureTask<Thread02>) rClass.newInstance();
                    LOGGER.info(runnable.get()+"这类线程执行之后");*//*
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }*/
            }
        };
        for (int i = 0; i < 5; i++) {
            Future<String> submit = threadPoolExecutor.submit(new Thread02());
            try {
                LOGGER.info(submit.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
//            threadPoolExecutor.submit(new LiftOff());
        }
        threadPoolExecutor.shutdown();
        try {
            // 该方法调用会被阻塞，直到所有任务执行完毕并且shutdown请求被调用，
            // 或者参数中定义的timeout时间到达或者当前线程被打断，
            // 这几种情况任意一个发生了就会导致该方法的执行
            threadPoolExecutor.awaitTermination(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
